unit ImageTrainer;

interface

uses
  SysUtils, GR32, GR32_Layers, CannyEdge, FannNetwork, GR32_OrdinalMaps,dialogs,
  GR32_FloatMap,Grids;

type
  TImageTraner = class
  private
    FANN      : TFannNetwork;
    canny     : TCannyEdge;
    Src  : TBitmap32;
    Dst : TBitmap32;
    procedure GetRGB(Color32 :TColor32; var R,G,B: Byte);
  public
    constructor Create;
    procedure LoadNN(fileName: string);
    procedure SaveNN(fileName: string);
    function Learn(input, target: string): double;
    procedure Guess(bmp32 : TBitmap32; var map:TBitmap32);
    destructor Destroy; override;

end;

implementation

constructor TImageTraner.Create;
begin
  Src:= TBitmap32.Create;
  Dst:= TBitmap32.Create;
  Canny:= TCannyEdge.Create;
  FANN := TFannNetwork.Create(nil);
  with FANN do
  begin
    ActivationFunctionHidden := afFANN_SIGMOID;
    ActivationFunctionOutput := afFANN_SIGMOID;
    TrainingAlgorithm := taFANN_TRAIN_RPROP;
    ConnectionRate := 1;
    LearningRate := 0.01;
    LearningMometum:=0.1;
    Randomize;

  end;
  with FANN.Layers do
  begin
    Add(IntToStr(4));
    Add(IntToStr(10));
    Add(IntToStr(10));
    Add(IntToStr(1));
  end;
  FANN.Build;

end;


procedure TImageTraner.GetRGB(Color32 : TColor32; var R,G,B : Byte);
begin
  R := (Color32 and $FF0000) shr 16;
  G := (Color32 and $FF00) shr 8;
  B :=  Color32 and $FF;
end;
destructor TImageTraner.Destroy;
begin
  FANN.UnBuild;
  FANN.Free;
  inherited;
end;
procedure TImageTraner.Guess(bmp32 : TBitmap32;var map: TBitmap32);
var
  X,Y: integer;
  inputs : array of Single;
  output: array of single;
  ColNumb : TColor32;
  R,G,B : Byte;
  edge,temp: integer;
begin
  setLength(inputs, 4);
  SetLength(output,1) ;
  Canny.CannyEdgeDetect(bmp32, Dst);
    for x:= 0 to bmp32.Width -1 do
      for y:= 0 to bmp32.Height -1 do
      begin
        edge:= dst[x,y];
        ColNumb := bmp32[x,y];
        GetRGB(ColNumb, R,G,B);
        inputs[0]   := R/255;
        inputs[1]   := G/255;
        inputs[2]   := B/255;
        if edge = 0 then inputs[3]:=0 else inputs[3] := 1;
        FANN.Run(inputs, output);
        temp:= round(output[0])*255;
        map[X,Y] := (temp shl 16) or (temp shl 8) or temp ;
     end;
     map.Changed;
end;

function  TImageTraner.Learn(input, target: string):double;
var
  X,Y: integer;
  edge: integer;
  inputs : array of Single;
  output: array of single;
  ColNumb : TColor32;
  R,G,B : Byte;
  error : double;
begin
  src.LoadFromFile(input);
  setLength(inputs, 4);
  SetLength(output,1) ;
  error := 0.0;
  Canny.CannyEdgeDetect(Src, Dst);
    for x:= 0 to src.width-1 do
      for y:= 0 to src.height-1 do
      begin
        edge:= dst[x,y];
        ColNumb := Src[x,y];
        GetRGB(ColNumb, R,G,B);
        inputs[0]   := R/255;
        inputs[1]   := G/255;
        inputs[2]   := B/255;
        if edge = 0 then inputs[3]:=0 else inputs[3] := 1;
        output[0] := StrToInt(target);
        error := FANN.Train(inputs, output);
     end;
     result:= error;
end;

procedure TImageTraner.LoadNN(fileName: string);
begin
  FANN.LoadFromFile(fileName);
  //FANN.Build;
end;

procedure TImageTraner.SaveNN(fileName: string);
begin
  FANN.SaveToFile(fileName);

end;
end.
